home *** CD-ROM | disk | FTP | other *** search
/ Clickx 53 / Clickx 53.iso / software / onmisbaretool / firefoxv301 / Firefox Setup 3.0.1.exe / nonlocalized / components / nsBrowserGlue.js < prev    next >
Encoding:
Text File  |  2008-07-02  |  27.4 KB  |  747 lines

  1. //@line 39 "e:\fx19rel\WINNT_5.2_Depend\mozilla\browser\components\nsBrowserGlue.js"
  2.  
  3. const Ci = Components.interfaces;
  4. const Cc = Components.classes;
  5. const Cr = Components.results;
  6. const Cu = Components.utils;
  7.  
  8. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  9. Cu.import("resource:///modules/distribution.js");
  10.  
  11. const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
  12.  
  13. // Check to see if bookmarks need backing up once per
  14. // day on 1 hour idle.
  15. const BOOKMARKS_ARCHIVE_IDLE_TIME = 60 * 60;
  16.  
  17. // Backup bookmarks once every 24 hours.
  18. const BOOKMARKS_ARCHIVE_INTERVAL = 86400 * 1000;
  19.  
  20. // Factory object
  21. const BrowserGlueServiceFactory = {
  22.   _instance: null,
  23.   createInstance: function (outer, iid) 
  24.   {
  25.     if (outer != null)
  26.       throw Components.results.NS_ERROR_NO_AGGREGATION;
  27.     return this._instance == null ?
  28.       this._instance = new BrowserGlue() : this._instance;
  29.   }
  30. };
  31.  
  32. // Constructor
  33.  
  34. function BrowserGlue() {
  35.   this._init();
  36. }
  37.  
  38. BrowserGlue.prototype = {
  39.   _saveSession: false,
  40.  
  41.   _setPrefToSaveSession: function()
  42.   {
  43.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  44.                      getService(Ci.nsIPrefBranch);
  45.     prefBranch.setBoolPref("browser.sessionstore.resume_session_once", true);
  46.   },
  47.  
  48.   // nsIObserver implementation 
  49.   observe: function(subject, topic, data) 
  50.   {
  51.     switch(topic) {
  52.       case "xpcom-shutdown":
  53.         this._dispose();
  54.         break;
  55.       case "quit-application": 
  56.         this._onProfileShutdown();
  57.         break;
  58.       case "prefservice:after-app-defaults":
  59.         this._onAppDefaults();
  60.         break;
  61.       case "final-ui-startup":
  62.         this._onProfileStartup();
  63.         break;
  64.       case "sessionstore-windows-restored":
  65.         this._onBrowserStartup();
  66.         break;
  67.       case "browser:purge-session-history":
  68.         // reset the console service's error buffer
  69.         const cs = Cc["@mozilla.org/consoleservice;1"].
  70.                    getService(Ci.nsIConsoleService);
  71.         cs.logStringMessage(null); // clear the console (in case it's open)
  72.         cs.reset();
  73.         break;
  74.       case "quit-application-requested":
  75.         this._onQuitRequest(subject, data);
  76.         break;
  77.       case "quit-application-granted":
  78.         if (this._saveSession) {
  79.           this._setPrefToSaveSession();
  80.         }
  81.         break;
  82.       case "session-save":
  83.         this._setPrefToSaveSession();
  84.         subject.QueryInterface(Ci.nsISupportsPRBool);
  85.         subject.data = true;
  86.         break;
  87.       case "idle":
  88.         if (this.idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
  89.           // Back up bookmarks.
  90.           this._archiveBookmarks();
  91.         }
  92.         break;
  93.     }
  94.   }, 
  95.  
  96.   // initialization (called on application startup) 
  97.   _init: function() 
  98.   {
  99.     // observer registration
  100.     const osvr = Cc['@mozilla.org/observer-service;1'].
  101.                  getService(Ci.nsIObserverService);
  102.     osvr.addObserver(this, "quit-application", false);
  103.     osvr.addObserver(this, "xpcom-shutdown", false);
  104.     osvr.addObserver(this, "prefservice:after-app-defaults", false);
  105.     osvr.addObserver(this, "final-ui-startup", false);
  106.     osvr.addObserver(this, "sessionstore-windows-restored", false);
  107.     osvr.addObserver(this, "browser:purge-session-history", false);
  108.     osvr.addObserver(this, "quit-application-requested", false);
  109.     osvr.addObserver(this, "quit-application-granted", false);
  110.     osvr.addObserver(this, "session-save", false);
  111.   },
  112.  
  113.   // cleanup (called on application shutdown)
  114.   _dispose: function() 
  115.   {
  116.     // observer removal 
  117.     const osvr = Cc['@mozilla.org/observer-service;1'].
  118.                  getService(Ci.nsIObserverService);
  119.     osvr.removeObserver(this, "quit-application");
  120.     osvr.removeObserver(this, "xpcom-shutdown");
  121.     osvr.removeObserver(this, "prefservice:after-app-defaults");
  122.     osvr.removeObserver(this, "final-ui-startup");
  123.     osvr.removeObserver(this, "sessionstore-windows-restored");
  124.     osvr.removeObserver(this, "browser:purge-session-history");
  125.     osvr.removeObserver(this, "quit-application-requested");
  126.     osvr.removeObserver(this, "quit-application-granted");
  127.     osvr.removeObserver(this, "session-save");
  128.   },
  129.  
  130.   _onAppDefaults: function()
  131.   {
  132.     // apply distribution customizations (prefs)
  133.     // other customizations are applied in _onProfileStartup()
  134.     var distro = new DistributionCustomizer();
  135.     distro.applyPrefDefaults();
  136.   },
  137.  
  138.   // profile startup handler (contains profile initialization routines)
  139.   _onProfileStartup: function() 
  140.   {
  141.     // Check to see if the EULA must be shown on startup
  142.  
  143.     // Global override for tinderbox machines
  144.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  145.                      getService(Ci.nsIPrefBranch);
  146.     var mustDisplayEULA = true;
  147.     try {
  148.       mustDisplayEULA = !prefBranch.getBoolPref("browser.EULA.override");
  149.     } catch (e) {
  150.       // Pref might not exist
  151.     }
  152.  
  153.     // Make sure it hasn't already been accepted
  154.     if (mustDisplayEULA) {
  155.       try {
  156.         var EULAVersion = prefBranch.getIntPref("browser.EULA.version");
  157.         mustDisplayEULA = !prefBranch.getBoolPref("browser.EULA." + EULAVersion + ".accepted");
  158.       } catch(ex) {
  159.       }
  160.     }
  161.  
  162.     if (mustDisplayEULA) {
  163.       var ww2 = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  164.                 getService(Ci.nsIWindowWatcher);
  165.       ww2.openWindow(null, "chrome://browser/content/EULA.xul", 
  166.                      "_blank", "chrome,centerscreen,modal,resizable=yes", null);
  167.     }
  168.  
  169.     this.Sanitizer.onStartup();
  170.     // check if we're in safe mode
  171.     var app = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).
  172.               QueryInterface(Ci.nsIXULRuntime);
  173.     if (app.inSafeMode) {
  174.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  175.                getService(Ci.nsIWindowWatcher);
  176.       ww.openWindow(null, "chrome://browser/content/safeMode.xul", 
  177.                     "_blank", "chrome,centerscreen,modal,resizable=no", null);
  178.     }
  179.  
  180.     // initialize Places
  181.     this._initPlaces();
  182.  
  183.     // apply distribution customizations
  184.     // prefs are applied in _onAppDefaults()
  185.     var distro = new DistributionCustomizer();
  186.     distro.applyCustomizations();
  187.  
  188.     // handle any UI migration
  189.     this._migrateUI();
  190.   },
  191.  
  192.   // profile shutdown handler (contains profile cleanup routines)
  193.   _onProfileShutdown: function() 
  194.   {
  195.     this._shutdownPlaces();
  196.     this.idleService.removeIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  197.     this.Sanitizer.onShutdown();
  198.   },
  199.  
  200.   // Browser startup complete. All initial windows have opened.
  201.   _onBrowserStartup: function()
  202.   {
  203.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  204.                      getService(Ci.nsIPrefBranch);
  205.     // If new add-ons were installed during startup open the add-ons manager.
  206.     if (prefBranch.prefHasUserValue(PREF_EM_NEW_ADDONS_LIST)) {
  207.       var args = Cc["@mozilla.org/supports-array;1"].
  208.                  createInstance(Ci.nsISupportsArray);
  209.       var str = Cc["@mozilla.org/supports-string;1"].
  210.                 createInstance(Ci.nsISupportsString);
  211.       str.data = "";
  212.       args.AppendElement(str);
  213.       var str = Cc["@mozilla.org/supports-string;1"].
  214.                 createInstance(Ci.nsISupportsString);
  215.       str.data = prefBranch.getCharPref(PREF_EM_NEW_ADDONS_LIST);
  216.       args.AppendElement(str);
  217.       const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
  218.       const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
  219.       var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
  220.                getService(Ci.nsIWindowWatcher);
  221.       ww.openWindow(null, EMURL, "_blank", EMFEATURES, args);
  222.       prefBranch.clearUserPref(PREF_EM_NEW_ADDONS_LIST);
  223.     }
  224.   },
  225.  
  226.   _onQuitRequest: function(aCancelQuit, aQuitType)
  227.   {
  228.     // If user has already dismissed quit request, then do nothing
  229.     if ((aCancelQuit instanceof Ci.nsISupportsPRBool) && aCancelQuit.data)
  230.       return;
  231.  
  232.     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
  233.              getService(Ci.nsIWindowMediator);
  234.  
  235.     var windowcount = 0;
  236.     var pagecount = 0;
  237.     var browserEnum = wm.getEnumerator("navigator:browser");
  238.     while (browserEnum.hasMoreElements()) {
  239.       windowcount++;
  240.  
  241.       var browser = browserEnum.getNext();
  242.       var tabbrowser = browser.document.getElementById("content");
  243.       if (tabbrowser)
  244.         pagecount += tabbrowser.browsers.length;
  245.     }
  246.  
  247.     this._saveSession = false;
  248.     if (pagecount < 2)
  249.       return;
  250.  
  251.     if (aQuitType != "restart")
  252.       aQuitType = "quit";
  253.  
  254.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  255.                      getService(Ci.nsIPrefBranch);
  256.     var showPrompt = true;
  257.     try {
  258.       // browser.warnOnQuit is a hidden global boolean to override all quit prompts
  259.       // browser.warnOnRestart specifically covers app-initiated restarts where we restart the app
  260.       // browser.tabs.warnOnClose is the global "warn when closing multiple tabs" pref
  261.  
  262.       var sessionWillBeSaved = prefBranch.getIntPref("browser.startup.page") == 3 ||
  263.                                prefBranch.getBoolPref("browser.sessionstore.resume_session_once");
  264.       if (sessionWillBeSaved || !prefBranch.getBoolPref("browser.warnOnQuit"))
  265.         showPrompt = false;
  266.       else if (aQuitType == "restart")
  267.         showPrompt = prefBranch.getBoolPref("browser.warnOnRestart");
  268.       else
  269.         showPrompt = prefBranch.getBoolPref("browser.tabs.warnOnClose");
  270.     } catch (ex) {}
  271.  
  272.     if (!showPrompt)
  273.       return false;
  274.  
  275.     var buttonChoice = 0;
  276.     var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].
  277.                         getService(Ci.nsIStringBundleService);
  278.     var quitBundle = bundleService.createBundle("chrome://browser/locale/quitDialog.properties");
  279.     var brandBundle = bundleService.createBundle("chrome://branding/locale/brand.properties");
  280.  
  281.     var appName = brandBundle.GetStringFromName("brandShortName");
  282.     var quitDialogTitle = quitBundle.formatStringFromName(aQuitType + "DialogTitle",
  283.                                                             [appName], 1);
  284.  
  285.     var message;
  286.     if (aQuitType == "restart")
  287.       message = quitBundle.formatStringFromName("messageRestart",
  288.                                                 [appName], 1);
  289.     else if (windowcount == 1)
  290.       message = quitBundle.formatStringFromName("messageNoWindows",
  291.                                                 [appName], 1);
  292.     else
  293.       message = quitBundle.formatStringFromName("message",
  294.                                                 [appName], 1);
  295.  
  296.     var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  297.                         getService(Ci.nsIPromptService);
  298.  
  299.     var flags = promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0 +
  300.                 promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_1 +
  301.                 promptService.BUTTON_POS_0_DEFAULT;
  302.  
  303.     var neverAsk = {value:false};
  304.     var button0Title, button2Title;
  305.     var button1Title = quitBundle.GetStringFromName("cancelTitle");
  306.     var neverAskText = quitBundle.GetStringFromName("neverAsk");
  307.  
  308.     if (aQuitType == "restart")
  309.       button0Title = quitBundle.GetStringFromName("restartTitle");
  310.     else {
  311.       flags += promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_2;
  312.       button0Title = quitBundle.GetStringFromName("saveTitle");
  313.       button2Title = quitBundle.GetStringFromName("quitTitle");
  314.     }
  315.  
  316.     buttonChoice = promptService.confirmEx(null, quitDialogTitle, message,
  317.                                  flags, button0Title, button1Title, button2Title,
  318.                                  neverAskText, neverAsk);
  319.  
  320.     switch (buttonChoice) {
  321.     case 2: // Quit
  322.       if (neverAsk.value)
  323.         prefBranch.setBoolPref("browser.tabs.warnOnClose", false);
  324.       break;
  325.     case 1: // Cancel
  326.       aCancelQuit.QueryInterface(Ci.nsISupportsPRBool);
  327.       aCancelQuit.data = true;
  328.       break;
  329.     case 0: // Save & Quit
  330.       this._saveSession = true;
  331.       if (neverAsk.value) {
  332.         if (aQuitType == "restart")
  333.           prefBranch.setBoolPref("browser.warnOnRestart", false);
  334.         else {
  335.           // always save state when shutting down
  336.           prefBranch.setIntPref("browser.startup.page", 3);
  337.         }
  338.       }
  339.       break;
  340.     }
  341.   },
  342.  
  343.   // returns the (cached) Sanitizer constructor
  344.   get Sanitizer() 
  345.   {
  346.     if(typeof(Sanitizer) != "function") { // we should dynamically load the script
  347.       Cc["@mozilla.org/moz/jssubscript-loader;1"].
  348.       getService(Ci.mozIJSSubScriptLoader).
  349.       loadSubScript("chrome://browser/content/sanitize.js", null);
  350.     }
  351.     return Sanitizer;
  352.   },
  353.  
  354.   _idleService: null,
  355.   get idleService() {
  356.     if (!this._idleService)
  357.       this._idleService = Cc["@mozilla.org/widget/idleservice;1"].
  358.                           getService(Ci.nsIIdleService);
  359.     return this._idleService;
  360.   },
  361.  
  362.   /**
  363.    * Initialize Places
  364.    * - imports the bookmarks html file if bookmarks datastore is empty
  365.    *
  366.    * These prefs are set by the backend services upon creation (or recreation)
  367.    * of the Places db:
  368.    * - browser.places.importBookmarksHTML
  369.    *   Set to false by the history service to indicate we need to re-import.
  370.    * - browser.places.smartBookmarksVersion
  371.    *   Set during HTML import to indicate that Smart Bookmarks were created.
  372.    *   Set to -1 to disable Smart Bookmarks creation.
  373.    *   Set to 0 to restore current Smart Bookmarks.
  374.    *
  375.    * These prefs are set up by the frontend:
  376.    * - browser.bookmarks.restore_default_bookmarks
  377.    *   Set to true by safe-mode dialog to indicate we must restore default
  378.    *   bookmarks.
  379.    */
  380.   _initPlaces: function bg__initPlaces() {
  381.     // we need to instantiate the history service before checking
  382.     // the browser.places.importBookmarksHTML pref, as
  383.     // nsNavHistory::ForceMigrateBookmarksDB() will set that pref
  384.     // if we need to force a migration (due to a schema change)
  385.     var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
  386.                   getService(Ci.nsINavHistoryService);
  387.  
  388.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  389.                      getService(Ci.nsIPrefBranch);
  390.  
  391.     var importBookmarks = false;
  392.     var restoreDefaultBookmarks = false;
  393.     try {
  394.       restoreDefaultBookmarks = prefBranch.getBoolPref("browser.bookmarks.restore_default_bookmarks");
  395.     } catch(ex) {}
  396.  
  397.     if (restoreDefaultBookmarks) {
  398.       // Ensure that we already have a bookmarks backup for today
  399.       this._archiveBookmarks();
  400.       // we will restore bookmarks from html
  401.       importBookmarks = true;
  402.     }
  403.     else {
  404.       try {
  405.         importBookmarks = prefBranch.getBoolPref("browser.places.importBookmarksHTML");
  406.       } catch(ex) {}
  407.     }
  408.  
  409.     if (!importBookmarks) {
  410.       // Call it here for Fx3 profiles created before the Places folder
  411.       // has been added, otherwise it's called during import.
  412.       this.ensurePlacesDefaultQueriesInitialized();
  413.     }
  414.     else {
  415.       // get latest backup
  416.       Cu.import("resource://gre/modules/utils.js");
  417.       var bookmarksFile = PlacesUtils.getMostRecentBackup();
  418.  
  419.       if (!restoreDefaultBookmarks &&
  420.           bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
  421.         // restore a JSON backup
  422.         PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
  423.       }
  424.       else {
  425.         // if there's no JSON backup or we are restoring default bookmarks
  426.  
  427.         // ensurePlacesDefaultQueriesInitialized() is called by import.
  428.         prefBranch.setIntPref("browser.places.smartBookmarksVersion", 0);
  429.  
  430.         var dirService = Cc["@mozilla.org/file/directory_service;1"].
  431.                          getService(Ci.nsIProperties);
  432.  
  433.         var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
  434.         if (restoreDefaultBookmarks || !bookmarksFile.exists()) {
  435.           // get bookmarks.html file from default profile folder
  436.           bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
  437.           bookmarksFile.append("bookmarks.html");
  438.         }
  439.  
  440.         // import the file
  441.         try {
  442.           var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
  443.                          getService(Ci.nsIPlacesImportExportService);
  444.           importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
  445.         } catch (err) {
  446.           // Report the error, but ignore it.
  447.           Cu.reportError(err);
  448.         }
  449.         prefBranch.setBoolPref("browser.places.importBookmarksHTML", false);
  450.         if (restoreDefaultBookmarks)
  451.           prefBranch.setBoolPref("browser.bookmarks.restore_default_bookmarks",
  452.                                  false);
  453.       }
  454.     }
  455.  
  456.     // Initialize bookmark archiving on idle.
  457.     // Once a day, either on idle or shutdown, bookmarks are backed up.
  458.     this.idleService.addIdleObserver(this, BOOKMARKS_ARCHIVE_IDLE_TIME);
  459.   },
  460.  
  461.   /**
  462.    * Places shut-down tasks
  463.    * - back up and archive bookmarks
  464.    * - export bookmarks as HTML, if so configured
  465.    *
  466.    * Note: quit-application-granted notification is received twice
  467.    *       so replace this method with a no-op when first called.
  468.    */
  469.   _shutdownPlaces: function bg__shutdownPlaces() {
  470.     // Backup and archive Places bookmarks.
  471.     this._archiveBookmarks();
  472.  
  473.     // Backup bookmarks to bookmarks.html to support apps that depend
  474.     // on the legacy format.
  475.     var prefs = Cc["@mozilla.org/preferences-service;1"].
  476.                 getService(Ci.nsIPrefBranch);
  477.     var autoExportHTML = false;
  478.     try {
  479.       autoExportHTML = prefs.getBoolPref("browser.bookmarks.autoExportHTML");
  480.     } catch(ex) {
  481.       Components.utils.reportError(ex);
  482.     }
  483.  
  484.     if (autoExportHTML) {
  485.       Cc["@mozilla.org/browser/places/import-export-service;1"].
  486.         getService(Ci.nsIPlacesImportExportService).
  487.         backupBookmarksFile();
  488.     }
  489.   },
  490.  
  491.   /**
  492.    * Back up and archive bookmarks
  493.    */
  494.   _archiveBookmarks: function nsBrowserGlue__archiveBookmarks() {
  495.     Cu.import("resource://gre/modules/utils.js");
  496.  
  497.     var lastBackup = PlacesUtils.getMostRecentBackup();
  498.  
  499.     // Backup bookmarks if there aren't any backups or 
  500.     // they haven't been backed up in the last 24 hrs.
  501.     if (!lastBackup ||
  502.         Date.now() - lastBackup.lastModifiedTime > BOOKMARKS_ARCHIVE_INTERVAL) {
  503.       var maxBackups = 5;
  504.       var prefs = Cc["@mozilla.org/preferences-service;1"].
  505.                   getService(Ci.nsIPrefBranch);
  506.       try {
  507.         maxBackups = prefs.getIntPref("browser.bookmarks.max_backups");
  508.       } catch(ex) {}
  509.  
  510.       PlacesUtils.archiveBookmarksFile(maxBackups, false /* don't force */);
  511.     }
  512.   },
  513.  
  514.   _migrateUI: function bg__migrateUI() {
  515.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
  516.  
  517.     var migration = 0;
  518.     try {
  519.       migration = prefBranch.getIntPref("browser.migration.version");
  520.     } catch(ex) {}
  521.  
  522.     if (migration == 0) {
  523.       // this code should always migrate pre-FF3 profiles to the current UI state
  524.  
  525.       // grab the localstore.rdf and make changes needed for new UI
  526.       this._rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
  527.       this._dataSource = this._rdf.GetDataSource("rdf:local-store");
  528.       this._dirty = false;
  529.  
  530.       var currentSet = this._rdf.GetResource("currentset");
  531.  
  532.       // get an nsIRDFResource for the nav-bar item
  533.       var navBar = this._rdf.GetResource("chrome://browser/content/browser.xul#nav-bar");
  534.       var target = this._getPersist(navBar, currentSet);
  535.       if (target && !/(?:^|,)unified-back-forward-button(?:$|,)/.test(target))
  536.         this._setPersist(navBar, currentSet, "unified-back-forward-button," + target);
  537.  
  538.       // force the RDF to be saved
  539.       if (this._dirty)
  540.         this._dataSource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush();
  541.  
  542.       // free up the RDF service
  543.       this._rdf = null;
  544.       this._dataSource = null;
  545.  
  546.       // update the migration version
  547.       prefBranch.setIntPref("browser.migration.version", 1);
  548.     }
  549.   },
  550.  
  551.   _getPersist: function bg__getPersist(aSource, aProperty) {
  552.     var target = this._dataSource.GetTarget(aSource, aProperty, true);
  553.     if (target instanceof Ci.nsIRDFLiteral)
  554.       return target.Value;
  555.     return null;
  556.   },
  557.  
  558.   _setPersist: function bg__setPersist(aSource, aProperty, aTarget) {
  559.     this._dirty = true;
  560.     try {
  561.       var oldTarget = this._dataSource.GetTarget(aSource, aProperty, true);
  562.       if (oldTarget) {
  563.         if (aTarget)
  564.           this._dataSource.Change(aSource, aProperty, oldTarget, this._rdf.GetLiteral(aTarget));
  565.         else
  566.           this._dataSource.Unassert(aSource, aProperty, oldTarget);
  567.       }
  568.       else {
  569.         this._dataSource.Assert(aSource, aProperty, this._rdf.GetLiteral(aTarget), true);
  570.       }
  571.     }
  572.     catch(ex) {}
  573.   },
  574.  
  575.   // ------------------------------
  576.   // public nsIBrowserGlue members
  577.   // ------------------------------
  578.   
  579.   sanitize: function(aParentWindow) 
  580.   {
  581.     this.Sanitizer.sanitize(aParentWindow);
  582.   },
  583.  
  584.   ensurePlacesDefaultQueriesInitialized: function() {
  585.     const SMART_BOOKMARKS_VERSION = 1;
  586.     const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
  587.     const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
  588.  
  589.     // XXX should this be a pref?  see bug #399268
  590.     const MAX_RESULTS = 10;
  591.  
  592.     var prefBranch = Cc["@mozilla.org/preferences-service;1"].
  593.                      getService(Ci.nsIPrefBranch);
  594.  
  595.     // get current smart bookmarks version
  596.     // By default, if the pref is not set up, we must create Smart Bookmarks
  597.     var smartBookmarksCurrentVersion = 0;
  598.     try {
  599.       smartBookmarksCurrentVersion = prefBranch.getIntPref(SMART_BOOKMARKS_PREF);
  600.     } catch(ex) {}
  601.  
  602.     // bail out if we don't have to create or update Smart Bookmarks
  603.     if (smartBookmarksCurrentVersion == -1 ||
  604.         smartBookmarksCurrentVersion >= SMART_BOOKMARKS_VERSION)
  605.       return;
  606.  
  607.     var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
  608.                 getService(Ci.nsINavBookmarksService);
  609.     var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
  610.                   getService(Ci.nsIAnnotationService);
  611.  
  612.     var callback = {
  613.       _placesBundle: Cc["@mozilla.org/intl/stringbundle;1"].
  614.                      getService(Ci.nsIStringBundleService).
  615.                      createBundle("chrome://browser/locale/places/places.properties"),
  616.  
  617.       _uri: function(aSpec) {
  618.         return Cc["@mozilla.org/network/io-service;1"].
  619.                getService(Ci.nsIIOService).
  620.                newURI(aSpec, null, null);
  621.       },
  622.  
  623.       runBatched: function() {
  624.         var smartBookmarks = [];
  625.         var bookmarksMenuIndex = 0;
  626.         var bookmarksToolbarIndex = 0;
  627.  
  628.         // MOST VISITED
  629.         var smart = {queryId: "MostVisited", // don't change this
  630.                      itemId: null,
  631.                      title: this._placesBundle.GetStringFromName("mostVisitedTitle"),
  632.                      uri: this._uri("place:queryType=" +
  633.                                     Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY +
  634.                                     "&sort=" +
  635.                                     Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
  636.                                     "&maxResults=" + MAX_RESULTS),
  637.                      parent: bmsvc.toolbarFolder,
  638.                      position: bookmarksToolbarIndex++};
  639.         smartBookmarks.push(smart);
  640.  
  641.         // RECENTLY BOOKMARKED
  642.         smart = {queryId: "RecentlyBookmarked", // don't change this
  643.                  itemId: null,
  644.                  title: this._placesBundle.GetStringFromName("recentlyBookmarkedTitle"),
  645.                  uri: this._uri("place:folder=BOOKMARKS_MENU" +
  646.                                 "&folder=UNFILED_BOOKMARKS" +
  647.                                 "&folder=TOOLBAR" +
  648.                                 "&queryType=" +
  649.                                 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
  650.                                 "&sort=" +
  651.                                 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
  652.                                 "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
  653.                                 "&maxResults=" + MAX_RESULTS +
  654.                                 "&excludeQueries=1"),
  655.                  parent: bmsvc.bookmarksMenuFolder,
  656.                  position: bookmarksMenuIndex++};
  657.         smartBookmarks.push(smart);
  658.  
  659.         // RECENT TAGS
  660.         smart = {queryId: "RecentTags", // don't change this
  661.                  itemId: null,
  662.                  title: this._placesBundle.GetStringFromName("recentTagsTitle"),
  663.                  uri: this._uri("place:"+
  664.                     "type=" +
  665.                     Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY +
  666.                     "&sort=" +
  667.                     Ci.nsINavHistoryQueryOptions.SORT_BY_LASTMODIFIED_DESCENDING +
  668.                     "&maxResults=" + MAX_RESULTS),
  669.                  parent: bmsvc.bookmarksMenuFolder,
  670.                  position: bookmarksMenuIndex++};
  671.         smartBookmarks.push(smart);
  672.  
  673.         var smartBookmarkItemIds = annosvc.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, {});
  674.         // set current itemId, parent and position if Smart Bookmark exists
  675.         for each(var itemId in smartBookmarkItemIds) {
  676.           var queryId = annosvc.getItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  677.           for (var i = 0; i < smartBookmarks.length; i++){
  678.             if (smartBookmarks[i].queryId == queryId) {
  679.               smartBookmarks[i].itemId = itemId;
  680.               smartBookmarks[i].parent = bmsvc.getFolderIdForItem(itemId);
  681.               smartBookmarks[i].position = bmsvc.getItemIndex(itemId);
  682.               // remove current item, since it will be replaced
  683.               bmsvc.removeItem(itemId);
  684.               break;
  685.             }
  686.             // We don't remove old Smart Bookmarks because user could still
  687.             // find them useful, or could have personalized them.
  688.             // Instead we remove the Smart Bookmark annotation.
  689.             if (i == smartBookmarks.length - 1)
  690.               annosvc.removeItemAnnotation(itemId, SMART_BOOKMARKS_ANNO);
  691.           }
  692.         }
  693.  
  694.         // create smart bookmarks
  695.         for each(var smartBookmark in smartBookmarks) {
  696.           smartBookmark.itemId = bmsvc.insertBookmark(smartBookmark.parent,
  697.                                                       smartBookmark.uri,
  698.                                                       smartBookmark.position,
  699.                                                       smartBookmark.title);
  700.           annosvc.setItemAnnotation(smartBookmark.itemId,
  701.                                     SMART_BOOKMARKS_ANNO, smartBookmark.queryId,
  702.                                     0, annosvc.EXPIRE_NEVER);
  703.         }
  704.         
  705.         // If we are creating all Smart Bookmarks from ground up, add a
  706.         // separator below them in the bookmarks menu.
  707.         if (smartBookmarkItemIds.length == 0)
  708.           bmsvc.insertSeparator(bmsvc.bookmarksMenuFolder, bookmarksMenuIndex);
  709.       }
  710.     };
  711.  
  712.     try {
  713.       bmsvc.runInBatchMode(callback, null);
  714.     }
  715.     catch(ex) {
  716.       Components.utils.reportError(ex);
  717.     }
  718.     finally {
  719.       prefBranch.setIntPref(SMART_BOOKMARKS_PREF, SMART_BOOKMARKS_VERSION);
  720.       prefBranch.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
  721.     }
  722.   },
  723.  
  724.   // for XPCOM
  725.   classDescription: "Firefox Browser Glue Service",
  726.   classID:          Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
  727.   contractID:       "@mozilla.org/browser/browserglue;1",
  728.  
  729.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
  730.                                          Ci.nsISupportsWeakReference,
  731.                                          Ci.nsIBrowserGlue]),
  732.  
  733.   // redefine the default factory for XPCOMUtils
  734.   _xpcom_factory: BrowserGlueServiceFactory,
  735.  
  736.   // get this contractID registered for certain categories via XPCOMUtils
  737.   _xpcom_categories: [
  738.     // make BrowserGlue a startup observer
  739.     { category: "app-startup", service: true }
  740.   ]
  741. }
  742.  
  743. //module initialization
  744. function NSGetModule(aCompMgr, aFileSpec) {
  745.   return XPCOMUtils.generateModule([BrowserGlue]);
  746. }
  747.